package com.zxq.ruoyi.network.tcp.modbus;


import com.zxq.ruoyi.network.tcp.util.CrcUtils;

public class ModBusService implements IModelService {

    byte[] srcBytes = null;
    byte[] dstBytes = null;


    /**
     * 03   指令  读单个寄存器指令
     * 06   指令  写单个寄存器指令
     * 05	指令	 单继电器操作指令
     * 0F	指令  多继电器操作指令
     * 10	指令	 预置多个保持寄存器数值
     */
    final byte READ_SINGLE = 0x03;
    final byte WRITE_SINGLE = 0x06;
    final byte OPERATION_SINGLE = 0x05;
    final byte OPERATION_MORE = 0x0F;
    final byte PRECUT_MORE = 0x10;
    final byte ERROR_CODE = (byte) 0x85;


    /**
     * 是否为合法帧
     * @param frame
     * @return
     */
    @Override
    public boolean isLegalFrame(byte[] frame) {
        int dataLen = frame.length - 2;
        byte[] dataBuff = new byte[dataLen];
        System.arraycopy(frame,0,dataBuff,0,dataBuff.length);
        byte[] crcBuff = new byte[2];
        System.arraycopy(frame,0,dataBuff,0,dataBuff.length);
        System.arraycopy(frame,frame.length - 2,crcBuff,0,crcBuff.length);
        byte[] selfCrcBuff = CrcUtils.crc16(dataBuff);
        if(crcBuff[0] == selfCrcBuff[0] && crcBuff[1] == selfCrcBuff[1]) {
            return true;
        }
//        log.info("frame:" + HexBin.encode(frame));
//        log.info("data:" + HexBin.encode(dataBuff));
//        log.info("crc:" + HexBin.encode(crcBuff));
//        log.info("selfCrc:" + HexBin.encode(selfCrcBuff));
        return false;
    }

    @Override
    public void injectSrcBytes(byte[] srcBuff) {
         this.srcBytes = srcBuff;
    }


    /**
     * 01 03 00   00 00 0C 45 CF
     * 01 03 18   00FB    0170   01DF  36EF0000  0017  001F  0040    01C8  00BE   019F   0040   5621
     *           空气湿度   温度    CO2    光照      氮    磷     钾     湿度   温度   电导率    pH   验证码
     */

    @Override
    public boolean isModelBus(byte deviceByte, byte funByte) {
        if(srcBytes[0] == deviceByte && srcBytes[1] == funByte) {
            return true;
        }
        return false;
    }


    /**
     * 注意是 根据src帧来确定对应的帧
     * 写入的帧何读取的帧长度一样
     * 读取的帧长度3（设备地址1，指令1，长度1）
     * @return
     */
    @Override
    public int measureFrameLen() {
        int len = -1;
        switch (srcBytes[1]) {
            case READ_SINGLE:
               len = 3 + ((srcBytes[4]&0xff) * 256 + srcBytes[5]&0xff) * 2 + 2;
               break;
            case WRITE_SINGLE:
                len = 8;
                break;
            case OPERATION_SINGLE:
                len = 8;
                break;
            case OPERATION_MORE:
                len = 8;
                break;
            case PRECUT_MORE:
                len = 8;
                break;
            case ERROR_CODE:
                len = 5;
                break;
            default:
                len = -1;
                break;
           }
           return len;
    }





}
